package com.github.shiqiyue.app.config.file;

import com.github.shiqiyue.app.config.ApplicationConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.UUID;

/***
 * 文件服务
 * @author wenyao.wu
 * @date 2019/1/8
 */
@Slf4j
@Component
public class FileService {

    @Autowired
    private ApplicationConfig applicationConfig;


    /***
     * 文件根目录
     */
    private String localFileDirRoot;

    /***
     * 文件网络地址前缀
     */
    private String localFileUrlPrefix;


    @PostConstruct
    public void init() {
        localFileDirRoot = applicationConfig.getFileRootDir();
        localFileUrlPrefix = applicationConfig.getFileServer();
    }


    /***
     * 生成相对于根目录的文件路径
     * @param filePathEnum
     * @param fileName
     * @return
     */
    public String generatePath(FilePathEnum filePathEnum, String fileName) {
        String newFilename = generateNewFilename(fileName);
        String date = DateFormatUtils.format(new Date(), "/yyyy/MM/dd/");

        return localFileDirRoot + "/" + filePathEnum.getPath() + date + newFilename;
    }

    /***
     * 生成相对于根目录的文件目录路径
     * @param filePathEnum
     * @return
     */
    public String generateDirPath(FilePathEnum filePathEnum) {
        String date = DateFormatUtils.format(new Date(), "/yyyy/MM/dd/");

        return localFileDirRoot + "/" + filePathEnum.getPath() + date + UUID.randomUUID().toString();
    }

    /***
     * 创建临时文件
     * @param suffix
     * @return
     */
    public File createTempFile(String suffix) throws IOException {
        String path = generatePath(FilePathEnum.TEMP, suffix);
        File file = new File(path);
        FileUtils.forceMkdirParent(file);
        return file;
    }

    /***
     * 生成oss 对象名称
     * @param filePathEnum
     * @param fileName
     * @return
     */
    public String generateObjectName(FilePathEnum filePathEnum, String fileName) {
        String newFilename = generateNewFilename(fileName);
        String date = DateFormatUtils.format(new Date(), "/yyyy/MM/dd/");
        return filePathEnum.getPath() + date + newFilename;
    }


    /***
     * 生成新文件的名字
     * @param filename
     * @return
     */
    public String generateNewFilename(String filename) {
        String suffix = getFilenameSuffix(filename);
        String uuidStr = UUID.randomUUID().toString();
        return uuidStr + suffix;
    }

    /***
     * 生成文件路径
     *
     * @param fileType
     * @param filename
     * @return
     */
    public String generateNewFilePath(FilePathEnum fileType, String filename) {
        String suffix = getFilenameSuffix(filename);
        String uuidStr = UUID.randomUUID().toString();
        String dateStr = DateFormatUtils.format(new Date(), "/yyyy/MM/dd/");
        return fileType.getPath() + dateStr + uuidStr + suffix;
    }

    /***
     * 获取文件后缀
     * @param filename
     * @return
     */
    public String getFilenameSuffix(String filename) {
        return filename.substring(filename.lastIndexOf("."));
    }


    /***
     * 创建临时目录
     * @return
     */
    public File createTempDir() {
        String dirPath = generateDirPath(FilePathEnum.TEMP);
        return new File(dirPath);
    }

    public String getLocalFileDirRoot() {
        return localFileDirRoot;
    }

    /***
     * 缓存图片
     * @param url
     */
    public void cacheImage(String url, File file) throws IOException {
        URL aURL = new URL(url);
        String path = aURL.getPath();
        String filePath = localFileDirRoot + "/" + FilePathEnum.IMAGE.getPath() + path;
        FileUtils.copyFile(file, new File(filePath));
        log.info("缓存图片到图片缓存中:{}", path);
    }

    /***
     * 从缓存中获取图片
     * @param url
     * @return
     * @throws MalformedURLException
     */
    public File getFromImageCache(String url) throws MalformedURLException {
        URL aURL = new URL(url);
        String path = aURL.getPath();
        String filePath = localFileDirRoot + "/" + FilePathEnum.IMAGE.getPath() + path;
        File file = new File(filePath);
        if (file.exists()) {
            log.info("从图片缓存中获取图片:{}", path);
            return file;
        }
        return null;
    }

    public LocalFileSaveResult uploadFile(MultipartFile uploadFile, FilePathEnum filePathEnum) throws IOException {
        File directory = new File(localFileDirRoot);
        FileUtils.forceMkdir(directory);
        String newFilename = generateNewFilePath(filePathEnum, uploadFile.getOriginalFilename());
        File file = FileUtils.getFile(directory, newFilename);
        if (!file.exists()) {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            file.createNewFile();
        }
        try (FileOutputStream fos = new FileOutputStream(file)) {
            IOUtils.copy(uploadFile.getInputStream(), fos);
        } catch (Exception e) {
            throw e;
        }
        LocalFileSaveResult fileSaveResult = new LocalFileSaveResult();
        fileSaveResult.setFileName(newFilename);
        fileSaveResult.setLocalFilePath(file.getAbsolutePath());
        fileSaveResult.setFileUrl(localFileUrlPrefix + newFilename);
        return fileSaveResult;
    }

    public LocalFileSaveResult uploadFile(String filePath) {
        LocalFileSaveResult localFileSaveResult = new LocalFileSaveResult();
        localFileSaveResult.setLocalFilePath(filePath);
        localFileSaveResult.setFileUrl(localFileUrlPrefix + filePath.replace(localFileDirRoot, ""));
        return localFileSaveResult;
    }
}
